#include "main/inc/sys_utils.h"
#include "main/inc/sys_fun.h"

// 初始化
void lvgl_fbdev_init(void)
{
    /* 初始化 LittlevGL */
    lv_init();

    /* 初始化 Linux 帧缓冲设备 */
    fbdev_init();

    /* 为 LittlevGL 提供一个小缓冲区，用于绘制屏幕内容 */
    static lv_color_t buf[DISP_BUF_SIZE];

    /* 初始化缓冲区描述符 */
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    /* 初始化并注册一个显示驱动程序 */
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf = &disp_buf;   // 设置绘制缓冲区
    disp_drv.flush_cb = fbdev_flush; // 设置刷新回调函数
    disp_drv.hor_res  = 800;         // 设置水平分辨率
    disp_drv.ver_res  = 480;         // 设置垂直分辨率
    lv_disp_drv_register(&disp_drv); // 注册显示驱动程序

    evdev_init(); // 初始化事件设备
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1);          // 基本初始化
    indev_drv_1.type = LV_INDEV_TYPE_POINTER; // 设置输入设备类型为指针

    /* 此函数将定期被库调用，以获取鼠标的位置和状态 */
    indev_drv_1.read_cb      = evdev_read;                          // 设置读取回调函数
    lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv_1); // 注册输入设备驱动程序

    /* 为鼠标设置一个光标 */
    LV_IMG_DECLARE(mouse_cursor_icon)                    // 声明鼠标光标图标
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); // 创建一个图像对象作为光标
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);      // 设置图像源
    lv_indev_set_cursor(mouse_indev, cursor_obj);        // 将图像对象连接到驱动程序
    // 隐藏鼠标光标
    lv_obj_add_flag(cursor_obj, LV_OBJ_FLAG_HIDDEN);
}

// 任务循环
void lv_task_loop(void)
{
    /* 处理 LittlevGL 任务（无滴答模式）*/
    while(1) {
        lv_timer_handler(); // 处理定时器任务
        usleep(5000);       // 延时 5 毫秒
    }
}

/* 在 lv_conf.h 中设置为 `LV_TICK_CUSTOM_SYS_TIME_EXPR` */
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0; // 开始时间（毫秒）
    if(start_ms == 0) {
        struct timeval tv_start;                                          // 开始时间结构体
        gettimeofday(&tv_start, NULL);                                    // 获取当前时间
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000; // 转换为毫秒
    }

    struct timeval tv_now;                                      // 当前时间结构体
    gettimeofday(&tv_now, NULL);                                // 获取当前时间
    uint64_t now_ms;                                            // 当前时间（毫秒）
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000; // 转换为毫秒

    uint32_t time_ms = now_ms - start_ms; // 计算经过的时间（毫秒）
    return time_ms;                       // 返回经过的时间
}